import json
from httprunner.models import RequestData, ResponseData
from httprunner.utils import lower_dict_keys, omit_long_data
from robot.api import logger


class HttpRunnerHelp:

    @staticmethod
    def log_req_resp_record(resp_obj):
        """ get request and response info from Response() object.
        """

        def log_print(req_or_resp, r_type):
            msg = f"\n================== {r_type} details ==================\n"
            for key, value in req_or_resp.dict().items():
                if isinstance(value, dict):
                    value = json.dumps(value, indent=4)

                msg += "{:<8} : {}\n".format(key, value)
            logger.info(msg)

        # record actual request info
        request_headers = dict(resp_obj.request.headers)
        request_cookies = resp_obj.request._cookies.get_dict()

        request_body = resp_obj.request.body
        if request_body is not None:
            try:
                request_body = json.loads(request_body)
            except json.JSONDecodeError:
                # str: a=1&b=2
                pass
            except UnicodeDecodeError:
                # bytes/bytearray: request body in protobuf
                pass
            except TypeError:
                # neither str nor bytes/bytearray, e.g. <MultipartEncoder>
                pass

            request_content_type = lower_dict_keys(request_headers).get("content-type")
            if request_content_type and "multipart/form-data" in request_content_type:
                # upload file type
                request_body = "upload file stream (OMITTED)"

        request_data = RequestData(
            method=resp_obj.request.method,
            url=resp_obj.request.url,
            headers=request_headers,
            cookies=request_cookies,
            body=request_body,
        )

        # log request details in debug mode
        log_print(request_data, "request")

        # record response info
        resp_headers = dict(resp_obj.headers)
        lower_resp_headers = lower_dict_keys(resp_headers)
        content_type = lower_resp_headers.get("content-type", "")

        if "image" in content_type:
            # response is image type, record bytes content only
            response_body = resp_obj.content
        else:
            try:
                # try to record json data
                response_body = resp_obj.json()
            except Exception:   # 修改，处理所有异常
                # only record at most 512 text charactors
                resp_text = resp_obj.text
                response_body = omit_long_data(resp_text)

        response_data = ResponseData(
            status_code=resp_obj.status_code,
            cookies=resp_obj.cookies or {},
            encoding=resp_obj.encoding,
            headers=resp_headers,
            content_type=content_type,
            body=response_body,
        )

        # log response details in debug mode
        log_print(response_data, "response")
